package com.bestcem.xm.ticket.grpc.client;

import cn.hutool.core.lang.ObjectId;
import com.bestcem.xm.common.core.constant.GrpcClientNames;
import com.bestcem.xm.survey.grpc.v1.services.*;
import com.bestcem.xm.ticket.grpc.client.convert.TicketBaseSurveyConvert;
import com.bestcem.xm.ticket.grpc.client.dto.survey.ColumnDTO;
import com.bestcem.xm.ticket.grpc.client.dto.survey.ContactNodeDTO;
import com.bestcem.xm.ticket.grpc.client.dto.survey.RespondentDTO;
import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Timestamps;
import lombok.extern.slf4j.Slf4j;
import net.devh.boot.grpc.client.inject.GrpcClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import zhongyan.xm.base.v1.Base;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * 工单调用 survey 模块相关rpc接口客户端
 *
 * @author zq.ding <zq.ding@idiaoyan.com>
 * @version v1.0
 * @date 2021/8/31 14:06
 */
@Slf4j
@Service
public class TicketSurveyGrpcService {

    @GrpcClient(GrpcClientNames.DS_SURVEY)
    private BpSurveyTicketServiceGrpc.BpSurveyTicketServiceBlockingStub bpSurveyTicketServiceBlockingStub;
    @GrpcClient(GrpcClientNames.DS_SURVEY)
    private BpSurveyServiceGrpc.BpSurveyServiceBlockingStub bpSurveyServiceBlockingStub;

    /**
     * 根据 指定时间获取问卷的 答卷数量
     *
     * @param projectId 问卷ID
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @return java.lang.Integer
     * @author zq.ding <zq.ding@idiaoyan.com>
     * @date 2021/8/31 18:20
     */
    @Nullable
    public Integer getFinishedRespondentCountByTimeRange(@Nonnull String projectId,
                                                         LocalDateTime startTime,
                                                         LocalDateTime endTime) {
        GetFinishedRespondentCountByTimeRangeRequest.Builder builder = GetFinishedRespondentCountByTimeRangeRequest.newBuilder();
        builder.setProjectId(projectId);
        if (Objects.nonNull(startTime)) {
            builder.setStartTime(localDateTimetoGoogleTimestamp(startTime));
        }
        if (Objects.nonNull(endTime)) {
            builder.setEndTime(localDateTimetoGoogleTimestamp(endTime));
        }

        try {
            GetFinishedRespondentCountByTimeRangeResponse response = bpSurveyTicketServiceBlockingStub.getFinishedRespondentCountByTimeRange(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY GetFinishedRespondentCountByTimeRange Error; projectId: {} ErrorMsg: {}",
                        projectId, response);
                return null;
            }
            return response.getCount();
        } catch (Exception e) {
            log.error("[Ticket] SURVEY GetFinishedRespondentCountByTimeRange Error; projectId: {}", projectId, e);
            return null;
        }

    }

    /**
     * 根据 seq 获取 答卷信息
     *
     * @param seq 答卷序号
     * @return 答卷信息
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/1 15:34
     */
    @Nullable
    public RespondentDTO getRespondentBySeq(Long seq, String projectId) {
        GetRespondentBySeqRequest.Builder builder = GetRespondentBySeqRequest.newBuilder();
        if (Objects.nonNull(seq)) {
            builder.setSeq(seq);
        }
        if (ObjectId.isValid(projectId)) {
            builder.setProjectId(projectId);
        }
        try {
            GetRespondentBySeqResponse response = bpSurveyTicketServiceBlockingStub.getRespondentBySeq(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY getRespondentBySeq Error; {},{}; ErrorMsg: {}", seq, projectId, response);
                return null;
            }
            return TicketBaseSurveyConvert.responseToRespondentDTO(response);
        } catch (Exception e) {
            log.error("[Ticket] SURVEY getRespondentBySeq Error; {},{}", seq, projectId, e);
            return null;
        }
    }

    /**
     * 根据 seq 获取 答卷信息 (拓展方法)
     *
     * @param seq    答卷序号
     * @param answer 是否需要答案，True: 需要, False: 不需要, default： False
     * @param extra  是否需要外部参数，True: 需要, False: 不需要, default： False
     * @param parse  是否需要对答案数据进行解析转换, True: 需要, False: 不需要, default： False
     * @param field  额外参数，不需要额外参数匹配时 传 ‘’
     * @param member 不需要 member 匹配时 传 null
     * @param userId 不需要 user_id 匹配时 传 ‘’
     * @return 答卷信息
     * @author zq.ding <zq.ding@idiaoyan.com>
     * @date 2021/8/31 18:21
     */
    @Nullable
    public RespondentDTO getRespondent(long seq,
                                       @Nullable Boolean answer, @Nullable Boolean extra, @Nullable Boolean parse,
                                       @Nullable String field, @Nullable Boolean member, @Nullable String userId,
                                       @Nullable String projectId) {
        GetRespondentBySeqRequest.Builder builder = GetRespondentBySeqRequest.newBuilder();
        builder.setSeq(seq);
        if (Objects.nonNull(answer)) {
            builder.setAnswer(answer);
        }
        if (Objects.nonNull(extra)) {
            builder.setExtra(extra);
        }
        if (Objects.nonNull(parse)) {
            builder.setParse(parse);
        }
        if (Objects.nonNull(field)) {
            builder.setField(field);
        }
        if (Objects.nonNull(member)) {
            builder.setMember(member);
        }
        if (Objects.nonNull(userId)) {
            builder.setUserId(userId);
        }
        if (ObjectId.isValid(projectId)) {
            builder.setProjectId(projectId);
        }

        try {
            GetRespondentBySeqResponse response = bpSurveyTicketServiceBlockingStub.getRespondentBySeq(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY getRespondent Error; {},{},{},{},{},{},{},{} ErrorMsg: {}",
                        seq, answer, extra, parse, field, member, userId, projectId, response);
                return null;
            }
            return TicketBaseSurveyConvert.responseToRespondentDTO(response);
        } catch (Exception e) {
            log.error("[Ticket] SURVEY getRespondent Error; {},{},{},{},{},{},{},{}",
                    seq, answer, extra, parse, field, member, userId, projectId, e);
            return null;
        }
    }

    /**
     * 获取添加额外参数数据的 Respondent
     *
     * @param respondentDTO RespondentDTO
     * @param userId        user_id
     * @param orgId         组织id
     * @return com.bestcem.xm.ticket.grpc.client.dto.survey.FilledRespondentInfoDTO
     * @author zq.ding <zq.ding@idiaoyan.com>
     * @date 2021/8/31 18:22
     */
    @Nonnull
    public RespondentDTO getFilledRespondentInfo(@Nonnull RespondentDTO respondentDTO, String userId, String orgId) {
        GetFilledRespondentInfoRequest.Builder builder = GetFilledRespondentInfoRequest.newBuilder();
        if (Objects.nonNull(respondentDTO.getSeq())) {
            builder.setSeq(respondentDTO.getSeq());
        }
        if (Objects.nonNull(respondentDTO.getProjectId())) {
            builder.setProjectId(respondentDTO.getProjectId());
        }
        if (StringUtils.isNotBlank(userId)) {
            builder.setUserId(userId);
        }
        if (StringUtils.isNotBlank(orgId)) {
            builder.setOrgId(orgId);
        }
        try {
            GetFilledRespondentInfoResponse response = bpSurveyTicketServiceBlockingStub.getFilledRespondentInfo(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY getFilledRespondentInfo Error;seq: {} userId: {} orgId: {} ErrorMsg: {}",
                        respondentDTO.getSeq(), userId, orgId, response);
                return respondentDTO;
            }
            return TicketBaseSurveyConvert.responseToRespondentDTO(respondentDTO, response);
        } catch (Exception e) {
            log.error("[Ticket] SURVEY getFilledRespondentInfo Error;seq: {} userId: {} orgId: {} ErrorMsg: {}",
                    respondentDTO.getSeq(), userId, orgId, e);
            return respondentDTO;
        }
    }

    /**
     * 根据 seq 获取答卷中 打分题的总分
     *
     * @param seq seq
     * @return 总分
     * @author <yuming.pan@idiaoyan.com>
     * @date 14:53 2021/8/31
     */
    @Nullable
    public Double getAnswerScoreBySeq(Long seq, String projectId) {
        GetAnswerScoreBySeqRequest.Builder builder = GetAnswerScoreBySeqRequest.newBuilder();
        if (Objects.nonNull(seq)) {
            builder.setSeq(seq);
        }
        if (ObjectId.isValid(projectId)) {
            builder.setProjectId(projectId);
        }
        try {
            GetAnswerScoreBySeqResponse response = bpSurveyTicketServiceBlockingStub.getAnswerScoreBySeq(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY getAnswerScoreBySeq {} Error; ErrorMsg: {}", seq, response);
                return null;
            }
            return response.getScore();
        } catch (Exception e) {
            log.error("[Ticket] SURVEY getAnswerScoreBySeq {} Error; ErrorMsg: {}", seq, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据 survey_id获取 问卷列
     *
     * @param surveyId 问卷id
     * @return 问卷列
     * @author <yuming.pan@idiaoyan.com>
     * @date 15:09 2021/8/31
     */
    @Nullable
    public List<ColumnDTO> getColumnsBySurveyId(String surveyId) {
        GetColumnsBySurveyIdRequest.Builder builder = GetColumnsBySurveyIdRequest.newBuilder();
        if (StringUtils.isNotEmpty(surveyId)) {
            builder.setSurveyId(surveyId);
        }
        try {
            GetColumnsBySurveyIdResponse response = bpSurveyTicketServiceBlockingStub.getColumnsBySurveyId(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY getColumnsBySurveyId {} Error; ErrorMsg: {}", surveyId, response);
                return null;
            }
            return TicketBaseSurveyConvert.responseToColumnDTOList(response);
        } catch (Exception e) {
            log.error("[Ticket] SURVEY getColumnsBySurveyId {} Error; ErrorMsg: {}", surveyId, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 通过seq查询答卷中的member_id
     *
     * @param seq 答卷seq
     * @return java.lang.String 联系人id
     * @author zq.ding <zq.ding@idiaoyan.com>
     * @date 2021/9/16 11:53
     */
    @Nullable
    public String getMemberIdBySeq(Integer seq) {
        GetMemberIdBySeqRequest.Builder builder = GetMemberIdBySeqRequest.newBuilder();
        if (Objects.nonNull(seq)) {
            builder.setSeq(seq);
        }
        try {
            GetMemberIdBySeqResponse response = bpSurveyServiceBlockingStub.getMemberIdBySeq(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY getMemberIdBySeq {} Error; ErrorMsg: {}", seq, response);
                return null;
            }
            return response.getMemberId();
        } catch (Exception e) {
            log.error("[Ticket] SURVEY getMemberIdBySeq {} Error; ErrorMsg: {}", seq, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据 project_id， user_id， seq 获取所有答卷数据
     *
     * @param projectId projectId
     * @param userId    用户id
     * @param seq       seq
     * @return 答卷数据
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 17:59 2021/9/18
     */
    @Nullable
    public String getAllRespondentData(@Nonnull String projectId, @Nonnull String userId, @Nonnull Long seq) {
        GetAllRespondentDataRequest.Builder builder = GetAllRespondentDataRequest.newBuilder();
        builder.setProjectId(projectId);
        builder.setUserId(userId);
        builder.setSeq(seq);
        try {
            GetAllRespondentDataResponse response = bpSurveyTicketServiceBlockingStub.getAllRespondentData(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY getAllRespondentData projectId={}, userId={}, seq={} Error; ErrorMsg: {}", projectId, userId, seq, response);
                return null;
            }
            return response.getData();
        } catch (Exception e) {
            log.error("[Ticket] EXP SURVEY getAllRespondentData projectId={}, userId={}, seq={} Error; ErrorMsg: {}", projectId, userId, seq, e.getMessage(), e);
            return null;
        }
    }

    /**
     * 根据seq 获取问卷联系人信息
     *
     * @param seq seq号
     * @return 联系人信息
     * @author ympan <yuming.pan@idiaoyan.com>
     * @date 18:12 2021/9/18
     */
    public ContactNodeDTO getContactBySeq(Long seq, String projectId) {
        GetContactBySeqRequest.Builder builder = GetContactBySeqRequest.newBuilder();
        if (Objects.nonNull(seq)) {
            builder.setSeq(seq);
        }
        if (ObjectId.isValid(projectId)) {
            builder.setProjectId(projectId);
        }
        try {
            GetContactBySeqResponse response = bpSurveyTicketServiceBlockingStub.getContactBySeq(builder.build());
            if (Objects.isNull(response) || Base.Code.ERROR.equals(response.getStatus().getCode())) {
                log.error("[Ticket] SURVEY getContactBySeq {} Error; ErrorMsg: {}", seq, response);
                return null;
            }
            return TicketBaseSurveyConvert.responseToContactNodeDTO(response);
        } catch (Exception e) {
            log.error("[Ticket] SURVEY getContactBySeq {} Error; ErrorMsg: {}", seq, e.getMessage(), e);
            return null;
        }
    }

    private Timestamp localDateTimetoGoogleTimestamp(LocalDateTime localDateTime) {
        if (localDateTime == null) {
            return null;
        }
        return Timestamps.fromMillis(localDateTimeToDate(localDateTime).getTime());
    }

    private Date localDateTimeToDate(LocalDateTime time) {
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = time.atZone(zoneId);
        return Date.from(zdt.toInstant());
    }
}
